﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;

namespace FBA.Client.Utils
{
    public partial class SerializeUtils
    {
        private static Dictionary<Type, object> dic = new Dictionary<Type, object>();

        public static T Get<T>()
        {
            if (!dic.ContainsKey(typeof(T)))
            {
                dic[typeof(T)] = null;
            }
            if (dic[typeof(T)] == null)
            {
                dic[typeof(T)] = Deserialize<T>();
            }
            if (dic[typeof(T)] == null)
            {
                dic[typeof(T)] = Activator.CreateInstance<T>();
            }
            return (T)dic[typeof(T)];
        }

        public static void Save<T>()
        {
            if (dic[typeof(T)] == null)
            {
                Serialize(Get<T>());
            }
            else
            {
                Serialize(dic[typeof(T)]);
            }
        }


        //序列化，失败的时候向上抛异常
        public static void Serialize(object graph)
        {
            string path = Md5(graph.GetType().FullName);
            using (FileStream fs = new FileStream(path, FileMode.Create))
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(fs, graph);
            }
        }

        //反序列化，失败的情况下返回null
        public static T Deserialize<T>()
        {
            string path = Md5(typeof(T).FullName);
            try
            {
                T graph;
                using (FileStream fs = new FileStream(path, FileMode.Open))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    graph = (T)bf.Deserialize(fs);
                }
                return graph;
            }
            catch (Exception)
            {
                return default(T);
            }
        }

        private static string Md5(Type type)
        {
            return Md5(type.FullName);
        }

        private static string Md5(string str)
        {
            MD5 md5Hasher = MD5.Create();
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(str));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }
    }
}
